home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / win / wmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-04  |  19.4 KB  |  704 lines

  1. #ifndef lint    )ØMhSid = "$Id: wmenu.c,v 1.3 1998/12/04 15:16:53 lhecking Exp $";
  2. #endif
  3.  
  4. /* GNUPLOT - win/wmenu.c */
  5. /*[
  6.  * Copyright 1992, 1993, 1998   Maurice Castro, Russell Lang
  7.  *
  8.  * Permission to use, copy, and distribute this software and its
  9.  * documentation for any purpose with or without fee is hereby granted,
  10.  * provided that the above copyright notice appear in all copies and
  11.  * that both that copyright notice and this permission notice appear
  12.  * in supporting documentation.
  13.  *
  14.  * Permission to modify the software is granted, but not the right to
  15.  * distribute the complete modified source code.  Modifications are to
  16.  * be distributed as patches to the released version.  Permission to
  17.  * distribute binaries produced by compiling modified sources is granted,
  18.  * provided you
  19.  *   1. distribute the corresponding source modifications from the
  20.  *    released version in the form of a patch file along with the binaries,
  21.  *   2. add special version identification to distinguish your version
  22.  *    in addition to the base release version number,
  23.  *   3. provide your name and address as the primary contact for the
  24.  *    support of your modified version, and
  25.  *   4. retain our contact information in regard to use of the base
  26.  *    software.
  27.  * Permission to distribute the released version of the source code along
  28.  * with corresponding source modifications in the form of a patch file is
  29.  * granted with same provisions 2 through 4 for binary distributions.
  30.  *
  31.  * This software is provided "as is" without express or implied warranty
  32.  * to the extent permitted by applicable law.
  33. ]*/
  34.  
  35. /*
  36.  * AUTHORS
  37.  * 
  38.  *   Maurice Castro
  39.  *   Russell Lang
  40.  * 
  41.  * Send your comments or suggestions to 
  42.  *  info-gnuplot@dartmouth.edu.
  43.  * This is a mailing list; to join it send a note to 
  44.  *  majordomo@dartmouth.edu.  
  45.  * Send bug reports to
  46.  *  bug-gnuplot@dartmouth.edu.
  47.  */
  48.  
  49. #define STRICT
  50. #include <windows.h>
  51. #include <windowsx.h>
  52. #if WINVER >= 0x030a
  53. #include <commdlg.h>
  54. #endif
  55. #include <string.h>    /* only use far items */
  56. #include "wgnuplib.h"
  57. #include "wresourc.h"
  58. #include "wcommon.h"
  59.  
  60. BOOL CALLBACK WINEXPORT InputBoxDlgProc(HWND, UINT, WPARAM, LPARAM);
  61. LRESULT CALLBACK WINEXPORT MenuButtonProc(HWND, UINT, WPARAM, LPARAM);
  62.  
  63. /* limits */
  64. #define MAXSTR 255
  65. #define MACROLEN 5000
  66. /* #define NUMMENU 256  defined in wresourc.h */
  67. #define MENUDEPTH 3
  68.  
  69. /* menu tokens */
  70. #define CMDMIN 129
  71. #define INPUT 129
  72. #define EOS 130
  73. #define OPEN 131
  74. #define SAVE 132
  75. #define CMDMAX 132
  76. char * keyword[] = {
  77.     "[INPUT]", "[EOS]", "[OPEN]", "[SAVE]",
  78.         "{ENTER}", "{ESC}", "{TAB}",
  79.         "{^A}", "{^B}", "{^C}", "{^D}", "{^E}", "{^F}", "{^G}", "{^H}", 
  80.     "{^I}", "{^J}", "{^K}", "{^L}", "{^M}", "{^N}", "{^O}", "{^P}", 
  81.     "{^Q}", "{^R}", "{^S}", "{^T}", "{^U}", "{^V}", "{^W}", "{^X}", 
  82.     "{^Y}", "{^Z}", "{^[}", "{^\\}", "{^]}", "{^^}", "{^_}",
  83.     NULL};
  84. BYTE keyeq[] = {
  85.     INPUT, EOS, OPEN, SAVE,
  86.         13, 27, 9,
  87.         1, 2, 3, 4, 5, 6, 7, 8,
  88.     9, 10, 11, 12, 13, 14, 15, 16,
  89.     17, 18, 19, 20, 21, 22, 23, 24, 
  90.     25, 26, 28, 29, 30, 31,
  91.     0};
  92.  
  93.  
  94. /* Send a macro to the text window */
  95. void
  96. SendMacro(LPTW lptw, UINT m)
  97. {
  98. BYTE FAR *s;
  99. char *d;
  100. char *buf;
  101. BOOL flag=TRUE;
  102. int i;
  103. LPMW lpmw = lptw->lpmw;
  104. #if WINVER >= 0x030a
  105. OPENFILENAME ofn;
  106. char *szTitle;
  107. char *szFile;
  108. char *szFilter;
  109. #endif
  110.  
  111.     if ( (buf = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  112.         return;
  113.  
  114.     if (m>=lpmw->nCountMenu)
  115.         return;
  116.     s = lpmw->macro[m];
  117.     d = buf;
  118.     *d = '\0';
  119.     while (s && *s && (d-buf < MAXSTR)) {
  120.         if (*s>=CMDMIN  && *s<=CMDMAX) {
  121.         switch (*s) {
  122.             case SAVE: /* [SAVE] - get a save filename from a file list box */
  123.             case OPEN: /* [OPEN] - get a filename from a file list box */
  124. #if WINVER >= 0x030a
  125.                 /* This uses COMMDLG.DLL from Windows 3.1 
  126.                    COMMDLG.DLL is redistributable */
  127.                 {
  128.                 BOOL save;
  129.                 if ( (szTitle = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  130.                     return;
  131.                 if ( (szFile = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  132.                     return;
  133.                 if ( (szFilter = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  134.                     return;
  135.  
  136.                 save = (*s==SAVE);
  137.                 s++;
  138.                         for(i=0; (*s >= 32 && *s <= 126); i++)
  139.                             szTitle[i] = *s++;    /* get dialog box title */
  140.                 szTitle[i]='\0';
  141.                 s++;
  142.                         for(i=0; (*s >= 32 && *s <= 126); i++)
  143.                             szFile[i] = *s++;    /* temporary copy of filter */
  144.                 szFile[i++]='\0';
  145.                 lstrcpy(szFilter,"Default (");
  146.                 lstrcat(szFilter,szFile);
  147.                 lstrcat(szFilter,")");
  148.                 i=lstrlen(szFilter);
  149.                 i++;    /* move past NULL */
  150.                 lstrcpy(szFilter+i,szFile);
  151.                 i+=lstrlen(szFilter+i);
  152.                 i++;    /* move past NULL */
  153.                 lstrcpy(szFilter+i,"All Files (*.*)");
  154.                 i+=lstrlen(szFilter+i);
  155.                 i++;    /* move past NULL */
  156.                 lstrcpy(szFilter+i,"*.*");
  157.                 i+=lstrlen(szFilter+i);
  158.                 i++;    /* move past NULL */
  159.                 szFilter[i++]='\0';    /* add a second NULL */
  160.                 flag = 0;
  161.  
  162.                 /* the Windows 3.1 implentation - MC */
  163.                 szFile[0] = '\0';
  164.                 /* clear the structrure */
  165.                 _fmemset(&ofn, 0, sizeof(OPENFILENAME));
  166.                 ofn.lStructSize = sizeof(OPENFILENAME);
  167.                 ofn.hwndOwner = lptw->hWndParent;
  168.                 ofn.lpstrFilter = szFilter;
  169.                 ofn.nFilterIndex = 1;
  170.                 ofn.lpstrFile = szFile;
  171.                 ofn.nMaxFile = MAXSTR;
  172.                 ofn.lpstrFileTitle = szFile;
  173.                 ofn.nMaxFileTitle = MAXSTR;
  174.                 ofn.lpstrTitle = szTitle;
  175.                 ofn.lpstrInitialDir = (LPSTR)NULL;
  176.                 ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  177.                 flag = (save ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn));
  178.                 if( flag ) {
  179.                     lpmw->nChar = lstrlen(ofn.lpstrFile);
  180.                     for (i=0; i<lpmw->nChar; i++)
  181.                         *d++=ofn.lpstrFile[i];
  182.                 }
  183.  
  184.                 LocalFreePtr((void NEAR *)OFFSETOF(szTitle));
  185.                 LocalFreePtr((void NEAR *)OFFSETOF(szFilter));
  186.                 LocalFreePtr((void NEAR *)OFFSETOF(szFile));
  187.  
  188.                 }
  189.                 break;
  190. #else
  191.                 /* Use InputBox if you don't have COMMDLG.DLL.
  192.                 s++;    /* skip list box title */
  193.                 for(i=0; (*s >= 32 && *s <= 126); i++)
  194.                     s++;
  195. #endif
  196.             case INPUT: /* [INPUT] - input a string of characters */
  197.                 s++;
  198.                 for(i=0; (*s >= 32 && *s <= 126); i++)
  199.                     lpmw->szPrompt[i] = *s++;
  200.                 lpmw->szPrompt[i]='\0';
  201. #ifdef WIN32
  202.                 flag = DialogBox( hdllInstance, "InputDlgBox", lptw->hWndParent, InputBoxDlgProc);
  203. #else
  204. #ifdef __DLL__
  205.                 lpmw->lpProcInput = (DLGPROC)GetProcAddress(hdllInstance, "InputBoxDlgProc");
  206. #else
  207.                 lpmw->lpProcInput = (DLGPROC)MakeProcInstance((FARPROC)InputBoxDlgProc, hdllInstance);
  208. #endif
  209.                 flag = DialogBox( hdllInstance, "InputDlgBox", lptw->hWndParent, lpmw->lpProcInput);
  210. #endif
  211.                 if( flag ) {
  212.                     for (i=0; i<lpmw->nChar; i++)
  213.                         *d++=lpmw->szAnswer[i];
  214.                 }
  215. #ifndef WIN32
  216. #ifndef __DLL__
  217.                 FreeProcInstance((FARPROC)lpmw->lpProcInput);
  218. #endif
  219. #endif
  220.                 break;
  221.             case EOS: /* [EOS] - End Of String - do nothing */
  222.                 default:
  223.                 s++;
  224.                 break;
  225.         }
  226.         if (!flag) { /* abort */
  227.             d = buf;
  228.             s = (BYTE FAR *)"";
  229.         }
  230.         }
  231.         else {
  232.         *d++ = *s++;
  233.         }
  234.     }
  235.     *d = '\0';
  236.     if (buf[0]!='\0') {
  237.         d = buf;
  238.         while (*d) {
  239.             SendMessage(lptw->hWndText,WM_CHAR,*d,1L);
  240.             d++;
  241.         }
  242.     }
  243. }
  244.  
  245.  
  246. #define GBUFSIZE 512
  247. typedef struct tagGFILE {
  248.     HFILE    hfile;
  249.     char     getbuf[GBUFSIZE];
  250.     int    getnext;
  251.     int    getleft;
  252. } GFILE;
  253.  
  254. GFILE * Gfopen(LPSTR lpszFileName, int fnOpenMode)
  255. {
  256. GFILE *gfile;
  257.     
  258.     gfile = (GFILE *)LocalAllocPtr(LHND, sizeof(GFILE));
  259.     if (!gfile)
  260.         return NULL;
  261.  
  262.     gfile->hfile = _lopen(lpszFileName, fnOpenMode);
  263.     if (gfile->hfile == HFILE_ERROR) {
  264.         LocalFreePtr((void NEAR *)OFFSETOF(gfile));
  265.         return NULL;
  266.     }
  267.     gfile->getleft = 0;
  268.     gfile->getnext = 0;
  269.     return gfile;
  270. }
  271.  
  272. void Gfclose(GFILE * gfile)
  273. {
  274.     
  275.     _lclose(gfile->hfile);
  276.     LocalFreePtr((void NEAR *)OFFSETOF(gfile));
  277.     return;
  278. }
  279.  
  280. /* returns number of characters read */
  281. int
  282. Gfgets(LPSTR lp, int size, GFILE *gfile)
  283. {
  284. int i;
  285. int ch;
  286.     for (i=0; i<size; i++) {
  287.         if (gfile->getleft <= 0) {
  288.             if ( (gfile->getleft = _lread(gfile->hfile, gfile->getbuf, GBUFSIZE)) == 0)
  289.                 break;
  290.             gfile->getnext = 0;
  291.         }
  292.         ch = *lp++ = gfile->getbuf[gfile->getnext++];
  293.         gfile->getleft --;
  294.         if (ch == '\r') {
  295.             i--;
  296.             lp--;
  297.         }
  298.         if (ch == '\n') {
  299.             i++;
  300.             break;
  301.         }
  302.     }
  303.     if (i<size)
  304.         *lp++ = '\0';
  305.     return i;
  306. }
  307.  
  308. /* Get a line from the menu file */
  309. /* Return number of lines read from file including comment lines */
  310. int GetLine(char * buffer, int len, GFILE *gfile)
  311. {
  312. BOOL  status;
  313. int nLine = 0;
  314.     
  315.    status = (Gfgets(buffer,len,gfile) != 0);
  316.    nLine++;
  317.    while( status && ( buffer[0] == 0 || buffer[0] == '\n' || buffer[0] == ';' ) ) {
  318.       /* blank line or comment - ignore */ 
  319.          status = (Gfgets(buffer,len,gfile) != 0);
  320.       nLine++;
  321.    }
  322.    if (lstrlen(buffer)>0)
  323.       buffer[lstrlen(buffer)-1] = '\0';    /* remove trailing \n */
  324.  
  325.    if (!status)
  326.       nLine = 0;    /* zero lines if file error */
  327.         
  328.     return nLine;
  329. }
  330.  
  331. /* Left justify string */
  332. void LeftJustify(char *d, char *s)
  333. {
  334.     while ( *s && (*s==' ' || *s=='\t') )
  335.         s++;    /* skip over space */
  336.     do {
  337.         *d++ = *s;
  338.     } while (*s++);
  339. }
  340.  
  341. /* Translate string to tokenized macro */
  342. void TranslateMacro(char *string)
  343. {
  344. int i, len;
  345. LPSTR ptr;
  346.  
  347.     for( i=0; keyword[i]!=(char *)NULL; i++ ) {
  348.         if( (ptr = _fstrstr( string, keyword[i] )) != NULL ) {
  349.             len = lstrlen( keyword[i] );
  350.             *ptr = keyeq[i];
  351.             lstrcpy( ptr+1, ptr+len );
  352.             i--;       /* allows for more than one occurrence of keyword */
  353.             }
  354.         }
  355. }
  356.  
  357. /* Load Macros, and create Menu from Menu file */
  358. void 
  359. LoadMacros(LPTW lptw)
  360. {
  361. GFILE *menufile;
  362. BYTE FAR *macroptr;
  363. char *buf;
  364. int nMenuLevel;
  365. HMENU hMenu[MENUDEPTH+1];
  366. LPMW lpmw;
  367. int nLine = 1;
  368. int nInc;
  369. HGLOBAL hmacro, hmacrobuf;
  370.  
  371. int i;
  372. HDC hdc;
  373. TEXTMETRIC tm;
  374. RECT rect;
  375. int ButtonX, ButtonY;
  376. char FAR *ButtonText[BUTTONMAX];
  377.  
  378.     lpmw = lptw->lpmw;
  379.  
  380.     /* mark all buffers and menu file as unused */
  381.     buf = (char *)NULL;
  382.     hmacro = 0;
  383.     hmacrobuf = 0;
  384.     lpmw->macro = (BYTE FAR * FAR *)NULL;
  385.     lpmw->macrobuf = (BYTE FAR *)NULL;
  386.     lpmw->szPrompt = (char *)NULL;
  387.     lpmw->szAnswer = (char *)NULL;
  388.     menufile = (GFILE *)NULL;
  389.  
  390.     /* open menu file */
  391.     if ((menufile=Gfopen(lpmw->szMenuName,OF_READ)) == (GFILE *)NULL)
  392.         goto errorcleanup;
  393.  
  394.     /* allocate buffers */
  395.     if ((buf = LocalAllocPtr(LHND, MAXSTR)) == (char *)NULL)
  396.         goto nomemory;
  397.     hmacro = GlobalAlloc(GHND,(NUMMENU) * sizeof(BYTE FAR *));
  398.     if ((lpmw->macro = (BYTE FAR * FAR *)GlobalLock(hmacro))  == (BYTE FAR * FAR *)NULL)
  399.         goto nomemory;
  400.     hmacrobuf = GlobalAlloc(GHND, MACROLEN);
  401.     if ((lpmw->macrobuf = (BYTE FAR*)GlobalLock(hmacrobuf)) == (BYTE FAR *)NULL)
  402.         goto nomemory;
  403.     if ((lpmw->szPrompt = LocalAllocPtr(LHND, MAXSTR)) == (char *)NULL)
  404.         goto nomemory;
  405.     if ((lpmw->szAnswer = LocalAllocPtr(LHND, MAXSTR)) == (char *)NULL)
  406.         goto nomemory;
  407.  
  408.     macroptr = lpmw->macrobuf;
  409.     lpmw->nButton = 0;
  410.     lpmw->nCountMenu = 0;
  411.     lpmw->hMenu = hMenu[0] = CreateMenu();
  412.     nMenuLevel = 0;
  413.  
  414.     while ((nInc = GetLine(buf,MAXSTR,menufile)) != 0) {
  415.       nLine += nInc;
  416.       LeftJustify(buf,buf);
  417.       if (buf[0]=='\0') {
  418.         /* ignore blank lines */
  419.       }
  420.       else if (!lstrcmpi(buf,"[Menu]")) {
  421.         /* new menu */
  422.         if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  423.             nLine += nInc;
  424.             wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  425.                     MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  426.             goto errorcleanup;
  427.         }
  428.         LeftJustify(buf,buf);
  429.         if (nMenuLevel<MENUDEPTH)
  430.             nMenuLevel++;
  431.         else {
  432.             wsprintf(buf,"Menu is too deep at line %d of %s\n",nLine,lpmw->szMenuName);
  433.                     MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  434.             goto errorcleanup;
  435.         }
  436.         hMenu[nMenuLevel] = CreateMenu();
  437.         AppendMenu(hMenu[nMenuLevel > 0 ? nMenuLevel-1 : 0],
  438.             MF_STRING | MF_POPUP, (UINT)hMenu[nMenuLevel], (LPCSTR)buf);
  439.       }
  440.       else if (!lstrcmpi(buf,"[EndMenu]")) {
  441.         if (nMenuLevel > 0)
  442.             nMenuLevel--;    /* back up one menu */
  443.       }
  444.       else if (!lstrcmpi(buf,"[Button]")) {
  445.         /* button macro */
  446.         if (lpmw->nButton >= BUTTONMAX) {
  447.             wsprintf(buf,"Too many buttons at line %d of %s\n",nLine,lpmw->szMenuName);
  448.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  449.             goto errorcleanup;
  450.         }
  451.         if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  452.             nLine += nInc;
  453.             wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  454.                     MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  455.             goto errorcleanup;
  456.         }
  457.         LeftJustify(buf,buf);
  458.         if (lstrlen(buf)+1 < MACROLEN - (macroptr-lpmw->macrobuf))
  459.             lstrcpy((char FAR *)macroptr,buf);
  460.         else {
  461.             wsprintf(buf,"Out of space for storing menu macros\n at line %d of \n",nLine,lpmw->szMenuName);
  462.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  463.             goto errorcleanup;
  464.         }
  465.         ButtonText[lpmw->nButton] = (char FAR *)macroptr;
  466.         macroptr += lstrlen((char FAR *)macroptr)+1;
  467.         *macroptr = '\0';
  468.         if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  469.             nLine += nInc;
  470.             wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  471.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  472.             goto errorcleanup;
  473.         }
  474.         LeftJustify(buf,buf);
  475.         TranslateMacro(buf);
  476.         if (lstrlen(buf)+1 < MACROLEN - (macroptr-lpmw->macrobuf))
  477.             lstrcpy((char FAR *)macroptr,buf);
  478.         else {
  479.             wsprintf(buf,"Out of space for storing menu macros\n at line %d of \n",nLine,lpmw->szMenuName);
  480.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  481.             goto errorcleanup;
  482.         }
  483.         lpmw->hButtonID[lpmw->nButton] = lpmw->nCountMenu;
  484.         lpmw->macro[lpmw->nCountMenu] = macroptr;
  485.         macroptr += lstrlen((char FAR *)macroptr)+1;
  486.         *macroptr = '\0';
  487.         lpmw->nCountMenu++;
  488.         lpmw->nButton++;
  489.       }
  490.       else {
  491.         /* menu item */
  492.         if (lpmw->nCountMenu>=NUMMENU) {
  493.             wsprintf(buf,"Too many menu items at line %d of %s\n",nLine,lpmw->szMenuName);
  494.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  495.             goto errorcleanup;
  496.         }
  497.         LeftJustify(buf,buf);
  498. /* HBB 981202: added MF_SEPARATOR to the MF_MENU*BREAK items. This  is meant
  499.  * to maybe avoid a CodeGuard warning about passing last argument zero
  500.  * when item style is not SEPARATOR... Actually, a better solution would
  501.  * have been to combine the '|' divider with the next menu item. */
  502.         if (buf[0]=='-') {
  503.             if (nMenuLevel == 0)
  504.                 AppendMenu(hMenu[0], MF_SEPARATOR | MF_MENUBREAK, 0, (LPSTR)NULL);
  505.             else
  506.             AppendMenu(hMenu[nMenuLevel], MF_SEPARATOR, 0, (LPSTR)NULL);
  507.         }
  508.         else if (buf[0]=='|') {
  509.             AppendMenu(hMenu[nMenuLevel], MF_SEPARATOR | MF_MENUBARBREAK, 0, (LPSTR)NULL);
  510.         }
  511.         else {
  512.             AppendMenu(hMenu[nMenuLevel],MF_STRING, lpmw->nCountMenu, (LPSTR)buf);
  513.             if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  514.                 nLine += nInc;
  515.                 wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  516.                         MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  517.                 goto errorcleanup;
  518.             }
  519.             LeftJustify(buf,buf);
  520.             TranslateMacro(buf);
  521.             if (lstrlen(buf)+1 < MACROLEN - (macroptr-lpmw->macrobuf))
  522.                 lstrcpy((char FAR *)macroptr,buf);
  523.             else {
  524.                 wsprintf(buf,"Out of space for storing menu macros\n at line %d of %s\n",nLine,lpmw->szMenuName);
  525.                         MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  526.                 goto errorcleanup;
  527.             }
  528.             lpmw->macro[lpmw->nCountMenu] = macroptr;
  529.             macroptr += lstrlen((char FAR *)macroptr)+1;
  530.             *macroptr = '\0';
  531.             lpmw->nCountMenu++;
  532.         }
  533.       }
  534.     }
  535.  
  536.     if ( (lpmw->nCountMenu - lpmw->nButton) > 0 ) {
  537.         /* we have a menu bar so put it on the window */
  538.         SetMenu(lptw->hWndParent,lpmw->hMenu);
  539.         DrawMenuBar(lptw->hWndParent);
  540.     }
  541.  
  542.     if (!lpmw->nButton)
  543.         goto cleanup;        /* no buttons */
  544.  
  545.     /* calculate size of buttons */
  546.     hdc = GetDC(lptw->hWndParent);
  547.     SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  548.     GetTextMetrics(hdc, &tm);
  549.     ButtonX = 8 * tm.tmAveCharWidth;
  550.     ButtonY = 6 * (tm.tmHeight + tm.tmExternalLeading) / 4;
  551.     ReleaseDC(lptw->hWndParent,hdc);
  552.  
  553.     /* move top of client text window down to allow space for buttons */
  554.     lptw->ButtonHeight = ButtonY+1;
  555.     GetClientRect(lptw->hWndParent, &rect);
  556.     SetWindowPos(lptw->hWndText, (HWND)NULL, 0, lptw->ButtonHeight,
  557.             rect.right, rect.bottom-lptw->ButtonHeight, 
  558.             SWP_NOZORDER | SWP_NOACTIVATE);
  559.  
  560.     /* create the buttons */
  561. #ifdef __DLL__
  562.     lpmw->lpfnMenuButtonProc = (WNDPROC)GetProcAddress(hdllInstance, "MenuButtonProc");
  563. #else
  564.     lpmw->lpfnMenuButtonProc = (WNDPROC)MakeProcInstance((FARPROC)MenuButtonProc, hdllInstance);
  565. #endif
  566.     for (i=0; i<lpmw->nButton; i++) {
  567.         lpmw->hButton[i] = CreateWindow("button", ButtonText[i],
  568.             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  569.                 i * ButtonX, 0,
  570.                 ButtonX, ButtonY,
  571.                 lptw->hWndParent, (HMENU)i,
  572.                 lptw->hInstance, lptw);
  573.         lpmw->lpfnButtonProc[i] = (WNDPROC) GetWindowLong(lpmw->hButton[i], GWL_WNDPROC);
  574.         SetWindowLong(lpmw->hButton[i], GWL_WNDPROC, (LONG)lpmw->lpfnMenuButtonProc);
  575.     }
  576.  
  577.     goto cleanup;
  578.  
  579.  
  580. nomemory:
  581.     MessageBox(lptw->hWndParent,"Out of memory",lptw->Title, MB_ICONEXCLAMATION);
  582. errorcleanup:
  583.     if (hmacro) {
  584.         GlobalUnlock(hmacro);
  585.         GlobalFree(hmacro);
  586.     }
  587.     if (hmacrobuf) {
  588.         GlobalUnlock(hmacrobuf);
  589.         GlobalFree(hmacrobuf);
  590.     }
  591.     if (lpmw->szPrompt != (char *)NULL)
  592.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szPrompt));
  593.     if (lpmw->szAnswer != (char *)NULL)
  594.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szAnswer));
  595.  
  596. cleanup:
  597.     if (buf != (char *)NULL)
  598.         LocalFreePtr((void NEAR *)OFFSETOF(buf));
  599.     if (menufile != (GFILE *)NULL)
  600.         Gfclose(menufile);
  601.     return;
  602.  
  603. }
  604.  
  605. void
  606. CloseMacros(LPTW lptw)
  607. {
  608. HGLOBAL hglobal;
  609. LPMW lpmw;
  610.     lpmw = lptw->lpmw;
  611.  
  612. #ifndef WIN32
  613. #ifndef __DLL__
  614.     if (lpmw->lpfnMenuButtonProc)
  615.         FreeProcInstance((FARPROC)lpmw->lpfnMenuButtonProc);
  616. #endif
  617. #endif
  618.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lpmw->macro) );
  619.     if (hglobal) {
  620.         GlobalUnlock(hglobal);
  621.         GlobalFree(hglobal);
  622.     }
  623.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lpmw->macrobuf) );
  624.     if (hglobal) {
  625.         GlobalUnlock(hglobal);
  626.         GlobalFree(hglobal);
  627.     }
  628.     if (lpmw->szPrompt != (char *)NULL)
  629.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szPrompt));
  630.     if (lpmw->szAnswer != (char *)NULL)
  631.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szAnswer));
  632. }
  633.  
  634.  
  635. /***********************************************************************/
  636. /* InputBoxDlgProc() -  Message handling routine for Input dialog box         */
  637. /***********************************************************************/
  638.  
  639. BOOL CALLBACK WINEXPORT
  640. InputBoxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  641. {
  642. LPTW lptw;
  643. LPMW lpmw;
  644.     lptw = (LPTW)GetWindowLong(GetParent(hDlg), 0);
  645.     lpmw = lptw->lpmw;
  646.  
  647.     switch( message) {
  648.         case WM_INITDIALOG:
  649.             SetDlgItemText( hDlg, ID_PROMPT, lpmw->szPrompt);
  650.             return( TRUE);
  651.  
  652.         case WM_COMMAND:
  653.             switch(LOWORD(wParam)) {
  654.                 case ID_ANSWER:
  655.                     return( TRUE);
  656.  
  657.                 case IDOK:
  658.                     lpmw->nChar = GetDlgItemText( hDlg, ID_ANSWER, lpmw->szAnswer, MAXSTR);
  659.                     EndDialog( hDlg, TRUE);
  660.                     return( TRUE);
  661.  
  662.                 case IDCANCEL:
  663.                     lpmw->szAnswer[0] = 0;
  664.                     EndDialog( hDlg, FALSE);
  665.                     return( TRUE);
  666.  
  667.                 default:
  668.                     return( FALSE);
  669.                 }
  670.         default:
  671.             return( FALSE);
  672.         }
  673.     }
  674.  
  675.  
  676. LRESULT CALLBACK WINEXPORT
  677. MenuButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  678. {
  679. LPTW lptw;
  680. LPMW lpmw;
  681. #ifdef WIN32
  682. LONG n = GetWindowLong(hwnd, GWL_ID);
  683. #else
  684. WORD n = GetWindowWord(hwnd, GWW_ID);
  685. #endif
  686.     lptw = (LPTW)GetWindowLong(GetParent(hwnd), 0);
  687.     lpmw = lptw->lpmw;
  688.  
  689.     switch(message) {
  690.         case WM_LBUTTONUP:
  691.             {
  692.             RECT rect;
  693.             POINT pt;
  694.             GetWindowRect(hwnd, &rect);
  695.             GetCursorPos(&pt);
  696.             if (PtInRect(&rect, pt))
  697.                 SendMessage(lptw->hWndText, WM_COMMAND, lpmw->hButtonID[n], 0L);
  698.             SetFocus(lptw->hWndText);
  699.             }
  700.             break;
  701.     }
  702.     return CallWindowProc((lpmw->lpfnButtonProc[n]), hwnd, message, wParam, lParam);
  703. }
  704.